#ifndef CONTACT_H
#define CONTACT_H
#include "AddPeople.pb.h"
#include "../httplib.h"
#define IP "127.0.0.1"
#define PORT 8086
class Contact
{

private:
    httplib::Client _client;

private:
    void BuildHttpBody(AddPeople::AddPeopleRequest &req)
    {
        std::cout << "请输入联系人姓名: ";
        std::string name;
        getline(std::cin, name);
        req.set_name(name);
        std::cout << "请输入联系人年龄: ";
        int age;
        std::cin >> age;
        req.set_age(age);
        std::cin.ignore(256, '\n');

        for (int i = 1;; i++)
        {
            std::cout << "请输入联系人电话" << i << "(只输入回车完成电话新增): ";
            std::string number;
            getline(std::cin, number);
            if (number.empty())
            {
                break;
            }
            // 返回指向一段指向phone字段的空间让我们进行操作
            AddPeople::AddPeopleRequest_Phone *phone = req.add_phone();
            phone->set_phone(number);
            std::cout << "选择此电话类型 (1、移动电话 2、固定电话) : ";
            int type;
            std::cin >> type;
            std::cin.ignore(256, '\n');
            switch (type)
            {
            case 1:
                phone->set_phone_type(AddPeople::AddPeopleRequest_Phone_PhoneType::AddPeopleRequest_Phone_PhoneType_MP);
                break;
            case 2:
                phone->set_phone_type(AddPeople::AddPeopleRequest_Phone_PhoneType::AddPeopleRequest_Phone_PhoneType_TEL);
                break;
            default:
                std::cout << "----非法选择，使用默认值！" << std::endl;
                break;
            }
        }
        AddPeople::Address address;
        std::cout << "请输入联系人家庭地址: ";
        std::string home_address;
        getline(std::cin, home_address);
        address.set_home_address(home_address);
        std::cout << "请输入联系人单位地址: ";
        std::string unit_address;
        getline(std::cin, unit_address);
        address.set_work_address(unit_address);
        // 返回一段可操作空间
        google::protobuf::Any *data = req.mutable_address();
        // 设置我们的any字段
        data->PackFrom(address);

        // 对其他联系方式oneof字段进行操作
        std::cout << "请选择要添加的其他联系方式(1、qq     2、微信号):";
        int other_contact;
        std::cin >> other_contact;
        std::cin.ignore(256, '\n');
        if (1 == other_contact)
        {
            std::cout << "请输入联系人qq号: ";
            std::string qq;
            getline(std::cin, qq);
            req.set_qq(qq);
        }
        else if (2 == other_contact)
        {
            std::cout << "请输入联系人微信号: ";
            std::string wechat;
            getline(std::cin, wechat);
            req.set_wechat(wechat);
        }
        else
        {
            std::cout << "选择有误，未成功设置其他联系方式！" << std::endl;
        }

        for (int i = 0;; i++)
        {
            std::cout << "请输入备注" << i + 1 << "标题(只输入回车完成备注新增):";
            std::string remark_key;
            std::getline(std::cin, remark_key);
            if (remark_key.empty())
            {
                break;
            }

            std::cout << "请输入备注" << i + 1 << "内容: ";
            std::string remark_value;
            getline(std::cin, remark_value);
            // 返回操作我们map的指针
            req.mutable_remark()->insert({remark_key, remark_value});
        }
    }

public:
    Contact() : _client(IP, PORT)
    {
    }
    void AddOnePeople()
    {
        // http的完整请求
        httplib::Request req;
        // 构建http请求的正文
        AddPeople::AddPeopleRequest request;
        // 从表中输入中拿到我们的联系人信息把我们的post中的body结构体填充完毕
        BuildHttpBody(request);
        // 进行序列化到http请求正文中
        std::string body_str;
        if (!request.SerializeToString(&body_str))
        {
            // 抛出异常
            throw ContactException("请求body序列化失败");
        }
        // 下面进行发送
        // res 里面包括我们的http的响应
        auto res = _client.Post("/contacts/add", body_str, "application/protobuf");
        if (!res)
        {
            std::string err_desc;
            err_desc.append("/contacts/add 链接错误！错误信息：")
                .append(httplib::to_string(res.error()));
            throw ContactException(err_desc);
        }
        // 进行反序列化我们的应答的body
        AddPeople::AddPeopleResponse response;
        bool parse = response.ParseFromString(res->body);
        if (!parse && res->status != 200)
        {
            // 反序列化失败 并且状态码出错
            std::string err_desc;
            err_desc.append("post '/contacts/add/' 失败：")
                .append(std::to_string(res->status))
                .append("(")
                .append(res->reason)
                .append(")");
            throw ContactException(err_desc);
        }
        else if (res->status != 200)
        {
            // 反序列化成功 但是状态码不对
            //  处理服务异常
            std::string err_desc;
            err_desc.append("post '/contacts/add/' 失败 ")
                .append(std::to_string(res->status))
                .append("(")
                .append(res->reason)
                .append(") 错误原因：")
                .append(response.error_desc());
            throw ContactException(err_desc);
        }
        else if (!response.success())
        {
            // 处理结果异常
            std::string err_desc;
            err_desc.append("post '/contacts/add/' 结果异常：")
                .append("异常原因：")
                .append(response.error_desc());
            throw ContactException(err_desc);
        }
        std::cout << "---> 新增联系人成功，联系人ID：" << response.uid() << std::endl;
    }
    void DelOnePeople()
    {
    }
    void FindOnePeople()
    {
    }
    void FindAllPeople()
    {
    }
};
#endif